<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>2025年份的生日礼物!</title>
    <style>
        #container {
            /* 修改初始状态为可见 */
            opacity: 1;
            width: 60vw;
            max-width: 800px;
            height: 40vh;
            min-height: max-content;
            background: white;
            border-radius: 15px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            padding: 20px;
            display: flex;
            flex-direction: column;
            justify-content: center;
            text-align: center;
            align-items: center;
            transition: all .6s ease-out;
        }

        img {
            max-width: 30vw;
            max-height: 40vh;
        }

        /* 添加隐藏状态 */
        #container.hidden {
            opacity: 0;
            transform: translate(-100%, 100%) rotate(60deg);
        }

        button {
            padding: 1em 2em;
            background-color: #007BFF;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
        }

        #getHint {
            position: fixed;
            bottom: 0em;
            width: 8em;
            right: 0;
            height: 4em;
            background-color: #ffffff33;
            color: black;
            transition: opacity 0.6s ease-out;
        }

        #getHint[disabled] {
            opacity: 0;
        }
    </style>
</head>

<body>
    <div id="container" class="hidden">
    </div>
    <button id="getHint" disabled>获取提示</button>
    <audio src="./birthday.m4a"></audio>

    <script>
        function createBPMScheduler(bpm, events) {
            let timer = null;
            let startTime = performance.now();
            let currentBeat = 0;

            // 计算每个节拍的毫秒数
            const beatInterval = 60000 / bpm;

            // 按节拍数排序事件，确保顺序执行
            const sortedEvents = [...events].sort((a, b) => a.beatStart - b.beatStart);
            let nextEventIndex = 0;
            let lastCalledBeat = 0;

            async function checkEvents() {
                if (nextEventIndex < sortedEvents.length && currentBeat >= sortedEvents[nextEventIndex].beatStart && currentBeat < sortedEvents[nextEventIndex].beatEnd && lastCalledBeat.toFixed() !== currentBeat.toFixed()) {
                    lastCalledBeat = currentBeat;
                    const event = sortedEvents[nextEventIndex];
                    try {
                        event.callback(currentBeat);
                    } catch (err) {
                        console.error('执行回调函数出错:', err);
                    }
                }
                if (nextEventIndex < sortedEvents.length && currentBeat >= sortedEvents[nextEventIndex].beatEnd) {
                    nextEventIndex++;
                }

            }

            function update() {
                const elapsed = performance.now() - startTime;
                currentBeat = elapsed / beatInterval;

                checkEvents();

                timer = requestAnimationFrame(update);
            }

            return {
                /**
                 * 开始节拍调度
                 */
                start() {
                    if (timer) return; // 防止重复启动
                    startTime = performance.now();
                    currentBeat = 0;
                    nextEventIndex = 0;
                    timer = requestAnimationFrame(update);
                },

                /**
                 * 停止节拍调度
                 */
                stop() {
                    if (timer) {
                        cancelAnimationFrame(timer);
                        timer = null;
                    }
                }
            };
        }
        function rhythmGame() {
            const content = document.querySelector('#container');
            content.innerHTML = `<p>你好呀！</p>
            <p>很高兴你玩到了这里！应该还挺不容易的吧？</p>
            <p>其实也挺感谢你平时忙这忙那还有时间陪我玩这个的www</p>
            <p>嗯，不论如何，都是又活了一年。实在是值得恭喜。</p>
            <p>不是很想活着，但也不是很敢去死吗...？貌似也没那么坏。</p>
            <p>至少到今天，你还好好的活着，以及... 每天或许都有新的有些许惊喜的体验。</p>
            <p>这样就好了吧！你还会在365天后再看见日出，看见烟花。</p>
            <p>生日快乐！我们明年再见！</p>`
            content.style.minWidth = "fit-content";
            content.style.minHeight = "fit-content";
            content.style.width = "0";
            content.style.height = "0";
            const audio = document.querySelector('audio');
            if (audio.paused) {
                const bpm = 60; // 设置 BPM
                const elements = [];
                elements.push(container);
                let once = false;
                let score = 0;
                const scheduler = createBPMScheduler(bpm, [
                    {
                        beatStart: 21,
                        beatEnd: 200,
                        callback: (beat) => {
                            console.log(beat)
                            const emojis = "🎉 🎂 🎈 🎊 🥳 🎁 🍰 🧁 🕯️ 🌟 ✨ 🎆 🎇 🥂 🍾 🍻 👑 🦄 🥰 💖 🎀".split(" ");

                            function placeElement() {
                                const emoji = emojis[Math.floor(Math.random() * emojis.length)];
                                const newElement = document.createElement('div');
                                newElement.innerText = emoji;
                                newElement.style.position = 'absolute';
                                newElement.style.fontSize = '4em';
                                newElement.style.zIndex = 1000;
                                newElement.style.transition = 'transform 0.5s ease-out, opacity 0.5s ease-out';
                                newElement.style.transform = 'translate(-50%, -50%)';
                                newElement.style.pointerEvents = 'auto'; // 确保可以点击
                                document.body.appendChild(newElement);

                                // 获取元素的大致尺寸（4em大约是64px）
                                const elementWidth = newElement.getBoundingClientRect().width;
                                const elementHeight = newElement.getBoundingClientRect().height;
                                document.body.removeChild(newElement); // 移除元素以获取尺寸

                                let attempts = 0;
                                const maxAttempts = 100; // 最大尝试次数，避免无限循环

                                let left, top;
                                let positionFound = false;

                                // 尝试找到一个不重叠的位置
                                while (attempts < maxAttempts && !positionFound) {
                                    attempts++;

                                    // 计算随机位置，考虑元素宽度/高度，确保不超出边界
                                    left = Math.random() * (visualViewport.width - elementWidth) + elementWidth / 2;
                                    top = Math.random() * (visualViewport.height - elementHeight) + elementHeight / 2;

                                    // 检查是否与现有元素重叠
                                    positionFound = true;
                                    for (const existingElement of elements) {
                                        const rect = existingElement.getBoundingClientRect();
                                        const existingLeft = rect.left + rect.width / 2;
                                        const existingTop = rect.top + rect.height / 2;

                                        // 计算距离
                                        const distance = Math.sqrt(
                                            Math.pow(left - existingLeft, 2) +
                                            Math.pow(top - existingTop, 2)
                                        );

                                        // 如果距离小于元素宽度，则认为重叠
                                        if (distance < rect.width) {
                                            positionFound = false;
                                            break;
                                        }
                                    }
                                }

                                // 如果找到合适位置，放置元素
                                if (positionFound) {
                                    newElement.style.left = `${left}px`;
                                    newElement.style.top = `${top}px`;
                                    document.body.appendChild(newElement);

                                    newElement.onclick = () => {
                                        document.body.removeChild(newElement);
                                        score++;
                                        // 从数组中移除
                                        const index = elements.indexOf(newElement);
                                        if (index > -1) {
                                            elements.splice(index, 1);
                                        }
                                    };

                                    elements.push(newElement);
                                } else {
                                    console.log('无法找到不重叠的位置');
                                }
                            }

                            // 使用示例
                            placeElement(); // 每次调用放置一个新元素
                        }
                    },
                    {
                        beatStart: 202,
                        beatEnd: 208,
                        callback: (beat) => {
                            if(once) return;
                            once = true;
                            container.innerHTML = `<p>你一共有效击打了${score}次！</p><p>生日快乐！我们明年再见！</p>`;
                        }
                    },
                ]);
                audio.play();
                setTimeout(() => {
                    scheduler.start();
                }, 100);
            }

        }
        const pages = {
            start: {
                dom: `<div class="content">
                        <h1>欢迎~ 在最开始就和你说生日快乐！~</h1>
                        <p>准备好开始这段应该还算简单轻松的小游戏了吗？</p>
                        <p>点击下面的按钮查看规则吧！</p>
                        <button onclick="location.hash='#/rules'">查看规则</button>
                      </div>`,
            },
            rules: {
                dom: `<div class="content">
                        <h1>规则</h1>
                        <p>你总会需要在<b>输入框中</b>输入答案。（某些关卡有特殊过关方法，会在题面标注。）</p>
                        <p>除前两关外，答案总会是英文的（可能亦有数字或某些符号）而不是中文或者其他语言，大小写随意。</p>
                        <p>如果有提示，你会在页面下方看见一个按钮，点击它可以查看提示。</p>
                        <p>你被允许搜索，或使用AI工具。</p>
                        <p>你被允许打开控制台（开发者工具），在某些关卡中你也需要。但请不要通过查看完整源代码的方式作弊。</p>
                        <h2>祝你玩得愉快！</h2>
                        <button onclick="location.hash='#/level-1'">开始游戏</button>
                    </div>`,
            },
            "level-1": {
                dom: `<div class="content">
                        <h1>Level 1</h1>
                        <p>请输入答案</p>
                        <input type="text" id="answer" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false">
                      </div>`,
                onInit: (container) => {
                    const input = container.querySelector('input');
                    input.oninput = () => {
                        const answer = input.value;
                        if (answer === '答案') {
                            location.hash = '#/level-2';
                        }
                    };
                },
                sequenceNeeded: 0,
                onDestroy: (container) => {
                    const input = container.querySelector('input');
                    input.oninput = null;
                }
            },
            "level-2": {
                dom: `<div class="content">
                        <h1>Level 2</h1>
                        <p>请输入答案</p>
                        <input type="text" id="answer" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false">
                      </div>`,
                hint: '题面是一样的，但你的阅读方式或许可以不一样。',
                onInit: (container) => {
                    const input = container.querySelector('input');
                    input.oninput = () => {
                        const answer = input.value;
                        if (answer === '入答案') {
                            location.hash = '#/level-3';
                        }
                    };
                },
                sequenceNeeded: 1,
                onDestroy: (container) => {
                    const input = container.querySelector('input');
                    input.oninput = null;
                }
            },
            "level-3": {
                dom: `<div class="content">
                        <h1>Level 3</h1>
                        <p>请进入第四关</p>
                      </div>`,
                hint: '规则中说，你需要在输入框中输入答案，你总会需要找一个地方输入的，那你的屏幕上现在哪里有输入框呢？',
                sequenceNeeded: 2,
            },
            "level-4": {
                dom: `<div class="content">
                        <h1>Level 4</h1>
                        <p>请进入第五关</p>
                      </div>`,
                hint: '规则中说，你可以打开控制台(开发者工具)。',
                sequenceNeeded: 3,
                onInit() {
                    console.log('答案是：level-five')
                    console.log('同样，你需要把答案输入在上一关你输入答案的位置。')
                }
            },
            "level-five": {
                dom: `<div class="content">
                        <h1>Level 5</h1>
                        <p>0, 1, 6, 8, 9</p>
                        <p>有一个数字是不一样的。它便是答案。</p>
                      </div>`,
                hint: '当我们看见数字时，我们事实上看见了它们。而此时不必在数学上思考它们。',
                sequenceNeeded: 4,
            },
            "1": {
                dom: `<div class="content">
                        <h1>Level 6</h1>
                        <img src="./tsukiwoaruiteiru.png">
                        <p>找到那位艺术家。</p>
                      </div>`,
                hint: '规则中还说，你可以使用搜索与AI工具。',
                sequenceNeeded: 5,
                onInit(container) {
                    document.body.style.background = 'rgb(29, 48, 132)';
                    container.style.background = 'rgb(29, 48, 132)';
                    container.style.color = 'white';
                },
                onDestroy(container) {
                    document.body.style.background = '';
                    container.style.background = '';
                    container.style.color = '';
                }
            },
            "n-buna": {
                dom: `<div class="content">
                    <h1>Level 7</h1>
                    <p>以及她的名字。</p>
                </div>`,
                hint: "请留意本页的背景颜色。请用下划线 _ 分隔那个名字。",
                sequenceNeeded: 6,
                onInit(container) {
                    document.body.style.background = '#39c5bb';
                    container.style.background = '#39c5bb';
                },
                onDestroy(container) {
                    document.body.style.background = '';
                    container.style.background = '';
                }
            },
            "hatsune_miku": {
                dom: `<div class="content">
                    <h1>Level 8</h1>
                    <p>6 2 777 7777</p>
                    <p>答案为4个英文字母。</p>
                </div>`,
                sequenceNeeded: 7,
                hint: "因为按键不够，人们不得不反复按下按键来输入字母。",
            },
            "mars": {
                dom: `<div class="content">
                    <h1>Level 9</h1>
                    <p>112.988470, 28.201821</p>
                </div>`,
                hint: "答案填入四位数字。更多的提示请找到一件衣服。",
                sequenceNeeded: 8,
            },
            "1912": {
                dom: `<div class="content">
                    <h1>Level 10</h1>
                    <p>x += 113;</p>
                </div>`,
                sequenceNeeded: 9,
            },
            "2025": {
                dom: `<div class="content">
                    <h1>Level 11</h1>
                    <p>我做错了事情。若是生活能像用电脑编辑一样就好了。（此关有特殊的进入下一关的方法)</p>
                </div>`,
                onInit: (container) => {
                    window.detectCtrlZ = (e) => {
                        if ((e.ctrlKey || e.metaKey) && e.keyCode === 90) {
                            location.hash = '#/level-11-cannot-enter-by-url';
                        }
                    }
                    document.addEventListener('keydown', detectCtrlZ);
                },
                onDestroy() {
                    document.removeEventListener('keydown', window.detectCtrlZ);
                },
                sequenceNeeded: 10,
            },
            "level-11-cannot-enter-by-url": {
                dom: `<div class="content">
                    <h1>Level 12</h1>
                    <img src="./crack.png" />
                    <p>答案是你上次发送这张表情的时间。</p>
                    <p>答案格式：YYYYMMDDHH</p>
                </div>`,
                hint: "或许会有偏差（？ 你可以多试几次。",
                sequenceNeeded: 11,
            },
            "2025040712": {
                dom: `<div class="content">
                    <h1>Level 13</h1>
                    <p>由于题面包含特殊字符且你很有可能想要复制题面，你可以点击<a href="https://e.yzcm.work/share?shareId=505322-iOIy1MREIY_1" target="_blank">链接</a>并在链接内全选复制以保证你复制了正确的东西。</p>
                    <p style="font-size: xx-small;" id="fillMe">ﾟωﾟﾉ= /｀ｍ´）ﾉ ~┻━┻   //*´∇｀*/ ['_']; o=(ﾟｰﾟ)  =_=3; c=(ﾟΘﾟ) =(ﾟｰﾟ)-(ﾟｰﾟ); (ﾟДﾟ) =(ﾟΘﾟ)= (o^_^o)/ (o^_^o);(ﾟДﾟ)={ﾟΘﾟ: '_' ,ﾟωﾟﾉ : ((ﾟωﾟﾉ==3) +'_') [ﾟΘﾟ] ,ﾟｰﾟﾉ :(ﾟωﾟﾉ+ '_')[o^_^o -(ﾟΘﾟ)] ,ﾟДﾟﾉ:((ﾟｰﾟ==3) +'_')[ﾟｰﾟ] }; (ﾟДﾟ) [ﾟΘﾟ] =((ﾟωﾟﾉ==3) +'_') [c^_^o];(ﾟДﾟ) ['c'] = ((ﾟДﾟ)+'_') [ (ﾟｰﾟ)+(ﾟｰﾟ)-(ﾟΘﾟ) ];(ﾟДﾟ) ['o'] = ((ﾟДﾟ)+'_') [ﾟΘﾟ];(ﾟoﾟ)=(ﾟДﾟ) ['c']+(ﾟДﾟ) ['o']+(ﾟωﾟﾉ +'_')[ﾟΘﾟ]+ ((ﾟωﾟﾉ==3) +'_') [ﾟｰﾟ] + ((ﾟДﾟ) +'_') [(ﾟｰﾟ)+(ﾟｰﾟ)]+ ((ﾟｰﾟ==3) +'_') [ﾟΘﾟ]+((ﾟｰﾟ==3) +'_') [(ﾟｰﾟ) - (ﾟΘﾟ)]+(ﾟДﾟ) ['c']+((ﾟДﾟ)+'_') [(ﾟｰﾟ)+(ﾟｰﾟ)]+ (ﾟДﾟ) ['o']+((ﾟｰﾟ==3) +'_') [ﾟΘﾟ];(ﾟДﾟ) ['_'] =(o^_^o) [ﾟoﾟ] [ﾟoﾟ];(ﾟεﾟ)=((ﾟｰﾟ==3) +'_') [ﾟΘﾟ]+ (ﾟДﾟ) .ﾟДﾟﾉ+((ﾟДﾟ)+'_') [(ﾟｰﾟ) + (ﾟｰﾟ)]+((ﾟｰﾟ==3) +'_') [o^_^o -ﾟΘﾟ]+((ﾟｰﾟ==3) +'_') [ﾟΘﾟ]+ (ﾟωﾟﾉ +'_') [ﾟΘﾟ]; (ﾟｰﾟ)+=(ﾟΘﾟ); (ﾟДﾟ)[ﾟεﾟ]='\\'; (ﾟДﾟ).ﾟΘﾟﾉ=(ﾟДﾟ+ ﾟｰﾟ)[o^_^o -(ﾟΘﾟ)];(oﾟｰﾟo)=(ﾟωﾟﾉ +'_')[c^_^o];(ﾟДﾟ) [ﾟoﾟ]='\"';(ﾟДﾟ) ['_'] ( (ﾟДﾟ) ['_'] (ﾟεﾟ+(ﾟДﾟ)[ﾟoﾟ]+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ (ﾟｰﾟ)+ (ﾟΘﾟ)+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ ((ﾟｰﾟ) + (ﾟΘﾟ))+ (ﾟｰﾟ)+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ (ﾟｰﾟ)+ ((ﾟｰﾟ) + (ﾟΘﾟ))+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (ﾟΘﾟ))+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ ((o^_^o) +(o^_^o))+ (ﾟｰﾟ)+ (ﾟДﾟ)[ﾟεﾟ]+((ﾟｰﾟ) + (ﾟΘﾟ))+ (c^_^o)+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟｰﾟ)+ ((o^_^o) - (ﾟΘﾟ))+ (ﾟДﾟ)[ﾟεﾟ]+(oﾟｰﾟo)+ ((ﾟｰﾟ) + (o^_^o))+ (ﾟДﾟ) .ﾟΘﾟﾉ+ ((ﾟｰﾟ) + (ﾟΘﾟ))+ (ﾟｰﾟ)+ (ﾟДﾟ)[ﾟεﾟ]+(oﾟｰﾟo)+ ((o^_^o) +(o^_^o))+ ((ﾟｰﾟ) + (ﾟｰﾟ))+ (ﾟｰﾟ)+ ((ﾟｰﾟ) + (ﾟｰﾟ))+ (ﾟДﾟ)[ﾟεﾟ]+(oﾟｰﾟo)+ ((o^_^o) +(o^_^o))+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (ﾟΘﾟ))+ (ﾟДﾟ) [ﾟΘﾟ]+ (ﾟДﾟ)[ﾟεﾟ]+((ﾟｰﾟ) + (o^_^o))+ ((o^_^o) - (ﾟΘﾟ))+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟｰﾟ)+ (c^_^o)+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ ((ﾟｰﾟ) + (ﾟΘﾟ))+ ((o^_^o) - (ﾟΘﾟ))+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ (ﾟｰﾟ)+ (ﾟΘﾟ)+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ ((o^_^o) +(o^_^o))+ ((o^_^o) +(o^_^o))+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ (ﾟｰﾟ)+ (ﾟΘﾟ)+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ ((o^_^o) +(o^_^o))+ (o^_^o)+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ (ﾟｰﾟ)+ (o^_^o)+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (ﾟΘﾟ))+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ ((ﾟｰﾟ) + (ﾟΘﾟ))+ (ﾟΘﾟ)+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ ((o^_^o) +(o^_^o))+ (c^_^o)+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ ((o^_^o) +(o^_^o))+ (ﾟｰﾟ)+ (ﾟДﾟ)[ﾟεﾟ]+((ﾟｰﾟ) + (ﾟΘﾟ))+ ((ﾟｰﾟ) + (ﾟΘﾟ))+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ ((ﾟｰﾟ) + (ﾟΘﾟ))+ (ﾟΘﾟ)+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ ((o^_^o) +(o^_^o))+ (o^_^o)+ (ﾟДﾟ)[ﾟεﾟ]+((ﾟｰﾟ) + (ﾟΘﾟ))+ ((ﾟｰﾟ) + (ﾟΘﾟ))+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ (ﾟｰﾟ)+ (ﾟΘﾟ)+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ ((ﾟｰﾟ) + (ﾟΘﾟ))+ ((ﾟｰﾟ) + (ﾟΘﾟ))+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ (ﾟｰﾟ)+ (ﾟΘﾟ)+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ ((ﾟｰﾟ) + (o^_^o))+ ((o^_^o) - (ﾟΘﾟ))+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ ((ﾟｰﾟ) + (ﾟΘﾟ))+ (ﾟΘﾟ)+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ ((ﾟｰﾟ) + (ﾟΘﾟ))+ ((o^_^o) +(o^_^o))+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟΘﾟ)+ (ﾟｰﾟ)+ ((ﾟｰﾟ) + (o^_^o))+ (ﾟДﾟ)[ﾟεﾟ]+(ﾟｰﾟ)+ ((o^_^o) - (ﾟΘﾟ))+ (ﾟДﾟ)[ﾟεﾟ]+((ﾟｰﾟ) + (ﾟΘﾟ))+ (ﾟΘﾟ)+ (ﾟДﾟ)[ﾟoﾟ]) (ﾟΘﾟ)) ('_');</p>
                </div>`,
                hint: "可爱吧！但是并不只有人类能看懂这些表情哦！",
                sequenceNeeded: 12,
            },
            "javascript-is-amazing": {
                dom: `<div class="content">
                    <h1 id="input" contenteditable="true">Level 14</h1>
                    <p>请进入第15关</p>
                </div>`,
                onInit(container) {
                    const input = container.querySelector('#input');
                    input.oninput = () => {
                        const answer = input.innerText;
                        if (answer.endsWith("15")) {
                            location.hash = '#/level-15-cannot-enter-by-url-again';
                        }
                    };
                },
                hint: '总有些地方是可以让你输入文本的，你说是吧！更何况这次这个输入框就放在页面里了。',
                sequenceNeeded: 13,
            },
            'level-15-cannot-enter-by-url-again': {
                dom: `<div class="content">
                    <h1>Level 15</h1>
                    <p>朴素的祝福，请输入你即将获得的托福考试成绩</p>
                </div>`,
                hint: "多给1分不怕你骄傲。",
                sequenceNeeded: 14,
            },
            "121": {
                dom: `<div class="content">
                    <h1>结束啦！</h1>
                    <p>恭喜你通过了游戏！接下来是音乐和或许是音游的时间（</p>
                    <button onclick="rhythmGame()">点击这里开始</button>
                </div>`,
                sequenceNeeded: 15,
            },
            "404": {
                dom: `<div class="content">
                        <h1>404</h1>
                        <p id="message"></p>
                        <button onclick="history.back()">返回</button>
                      </div>`,
                onInit: (container) => {
                    const message = container.querySelector('#message');
                    const randomList = [
                        '你来到了一个未知的地方，四周一片荒芜。',
                        '你走进了一片迷雾，前方似乎有光亮，但又似乎没有。',
                        '你发现自己置身于一个空旷的空间，四周没有任何标志。',
                        '在解析 answer.py 的第一行时，发生了神秘的错误，你被传送到了一个未知的空间。',
                        '你落入了虚无世界。',
                        '请不要放弃，保持你的决心！',
                        '这个答案好奇怪，我们不能理解。',
                        '你确定？这道问题的答案是这个吗？那么好，不对。'
                    ]
                    message.innerText = randomList[Math.floor(Math.random() * randomList.length)];
                },
            },
        };

        let currentPage = null;
        let maximumSequenceNumber = parseInt(localStorage.getItem('maximumSequenceNumber') || '0');
        const container = document.getElementById('container');

        // 修改后的加载逻辑
        function loadPage() {
            const path = (window.location.hash.replace(/^#\//, '') || 'start').toLocaleLowerCase();
            let page = pages[path] || pages['404'];
            if (page.sequenceNeeded && page.sequenceNeeded > maximumSequenceNumber) {
                page = pages['404'];
            }
            maximumSequenceNumber = Math.max(maximumSequenceNumber, (page.sequenceNeeded || 0) + 1);
            localStorage.setItem('maximumSequenceNumber', maximumSequenceNumber);

            const loadNow = () => {
                // 移除旧页面
                if (currentPage) {
                    currentPage.onDestroy && currentPage.onDestroy(container);
                    container.innerHTML = '';
                }

                // 加载新页面
                if (page) {
                    container.innerHTML = page.dom;
                    // 等待 DOM 渲染完成后执行 onInit
                    setTimeout(() => {
                        const hintButton = document.getElementById('getHint');
                        if (page.hint) {
                            hintButton.disabled = false;
                            hintButton.onclick = () => {
                                alert(page.hint);
                            };
                        } else {
                            hintButton.disabled = true;
                            hintButton.onclick = null;
                        }
                        page.onInit && page.onInit(container);
                    }, 0);

                    // 触发重排后移除隐藏状态
                    void container.offsetHeight;
                    container.classList.remove('hidden');
                }

                currentPage = page;
            }

            if (container.classList.contains('hidden')) {
                loadNow();
            } else {
                // 添加隐藏状态
                container.classList.add('hidden');

                // 在过渡结束后处理内容
                container.addEventListener('transitionend', function handler() {
                    container.removeEventListener('transitionend', handler);
                    loadNow();
                }, { once: true });
            }

        }

        window.addEventListener('hashchange', loadPage);
        window.addEventListener('load', () => {
            loadPage();
        });
    </script>
</body>

</html>